package com.ershi.spring.component;

import com.ershi.spring.component.aware.MyAware;
import com.ershi.spring.component.bdrpp.RegistryBean;
import com.ershi.spring.component.bf.Blue;
import com.ershi.spring.component.bf.MyFactoryBean;
import com.ershi.spring.component.bfpp.Computer;
import com.ershi.spring.component.lifestyle.Yellow;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author 二十
 * @since 2021/10/30 9:30 下午
 */
public class ComponentMainTest {

	private static AnnotationConfigApplicationContext ioc
			= new AnnotationConfigApplicationContext("com.ershi.spring.component");

	public static void main(String[] args) {

		/*BeanFactory接口*/
		//testBeanFactory();

		/*InitializingBean  DisposableBean*/
		//testInitializingBeanVsDisposableBean();

		/*BeanPostProcessor*/
		//testBeanPostprocessor();

		/*Aware接口*/
		//testAware();

		/*BeanFactoryPostProcessor*/
		//testBeanFactoryPostProcessor();

		/*BeanDefinitionRegistryPostProcessor*/
		//testBeanDefinitionRegistryPostProcessor();

		/*@EventListener && */
		//testEventListener();

		/*SmartInitializingSingleton*/
		//testSmartInitializingSingleton();

		/*ApplicationListener*/
		//testApplicationListener();

		//testPostConstructVsPreDestroy();

	}

	/**
	 * FactoryBean，显式往容器中导入一个bean
	 * 想要获取工厂bean？ &
	 */
	private static void testBeanFactory() {
		/*Blue blue = ioc.getBean(Blue.class);
		System.out.println("blue = " + blue);*/

		//MyFactoryBean bean = (MyFactoryBean) ioc.getBean("&myFactoryBean");
		Blue bean = (Blue) ioc.getBean("myFactoryBean");
		System.out.println("bean.getClass() = " + bean.getClass());
	}

	/**
	 * 断点调试 查看执行时机
	 */
	private static void testInitializingBeanVsDisposableBean() {
		Yellow yellow = ioc.getBean(Yellow.class);
		System.out.println("yellow = " + yellow);
		ioc.close();
	}

	/**
	 * 断点调试   查看执行时机
	 * <p>
	 * 默认情况下 ， 后置处理器会在每一个单实例bean执行前后执行
	 * 可不可以控制在指定的bean初始化前后执行？
	 * <p>
	 * 类型断言
	 */
	private static void testBeanPostprocessor() {

	}

	/**
	 * 断点查看执行时机
	 * 自定义组件想要使用Spring容器底层的一些组件（ApplicationContext，BeanFactory，xxx）自定义组件实现xxxAware
	 */
	private static void testAware() {
		MyAware myAware = ioc.getBean(MyAware.class);
		myAware.print();
	}

	/**
	 * 默认Computer对象是单实例的，
	 * 通过beanFactory的后置处理器处理之后，变成原型的
	 * <p>
	 * 执行时机：打断点
	 */
	private static void testBeanFactoryPostProcessor() {
		/*ioc容器创建的12个核心方法里面*/
		Computer computer = ioc.getBean(Computer.class);
		Computer computer2 = ioc.getBean(Computer.class);
		System.out.println(computer == computer2);
	}

	/**
	 * 通过打断点可以查看执行时机，这个组件是上面那个组件的儿子
	 * 插播一条广告：BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor之间的关系？
	 * BeanDefinitionRegistryPostProcessor 是 BeanFactoryPostProcessor的子类和扩展
	 * 它里面 搞了一个新的方法  postProcessBeanDefinitionRegistry ，可以往容器中注册更多的bd信息。
	 * <p>
	 * 扩展点：
	 * ①BeanFactoryPostProcessor 对bd信息进行修改
	 * ②postProcessBeanDefinitionRegistry 添加更多的bd信息
	 */
	private static void testBeanDefinitionRegistryPostProcessor() {
		RegistryBean registryBean = ioc.getBean("registryBean", RegistryBean.class);
		System.out.println("registryBean = " + registryBean);
	}

	private static void testEventListener() {
		ioc.publishEvent(new ApplicationEvent("hello，spring") {
			@Override
			public Object getSource() {
				return super.getSource();
			}
		});
	}

	/**
	 * 在所有的单实例bean 通过getBean方法完成初始化之后
	 * 就会去查找这个类型的SmartInitializingSingleton 的 组件 ，执行里面的 方法
	 */
	private static void testSmartInitializingSingleton() {
	}
	/**
	 * 写一个监听器继承ApplicationListener
	 * 指定其监听的事件类型
	 * 当相关类型的事件发布的时候，他就会接收到消息，做相关动作
	 *
	 * 如何自己发布一个事件？
	 * ioc.publicEvent();
	 */
	private static void testApplicationListener(){

		ioc.publishEvent(new ApplicationEvent("hello，spring") {
			@Override
			public Object getSource() {
				return super.getSource();
			}
		});
	}

	/**
	 * 这两个注解在spring的源码里面运行不起来，但是实际上是生效的
	 * JSR250 的规范啊，会在构造方法执行前后执行
	 */
	private static void testPostConstructVsPreDestroy() {

	}

	//((AnnotationConfigApplicationContext)ioc).close();
}
